﻿using System;
using System.Text;
using HK.Core.Common.Data;
using HK.Core.Encryption.Protocol;
using HK.Core.Extend;
using HK.Core.IO.Output;
using HK.Core.Serializable.Protocol.Data;
using HK.Core.Utils;
using HK.Editor.Common;
using HK.Editor.GUIEx.Drag;
using HK.Editor.GUIEx.Protocol.Data;
using HK.Editor.GUIEx.Protocol.Drag;
using HK.Editor.GUIEx.Protocol.Window;
using HK.Editor.GUIEx.Styles;
using HK.Editor.Utils;
using UnityEditor;
using UnityEngine;
using HLogger = HK.Core.Logs.Logger;
using Object = UnityEngine.Object;

namespace HK.Editor.GUIEx.Window
{
    
    /// <summary>
    /// 未知窗体选项异常
    /// </summary>
    public class UnknownWindowOperationException : NotImplementedException
    {
        public UnknownWindowOperationException(IWindow iWin) : 
            base($"Unknown Window Operation!(Type:{iWin.GetType().Name})") { }
    }
    
    /// <summary>
    /// 窗口基类
    /// </summary>
    public abstract class WindowBase : EditorWindow, IWindow
    {
        /// <summary>
        /// 初始化标志位
        /// </summary>
        public bool Initialized { get; private set; } = false;
        
        /// <summary>
        /// 数据目录
        /// </summary>
        public virtual string DataDir => null;

        /// <summary>
        /// 需要刷新标志位
        /// </summary>
        public bool NeedRefresh { get; protected set; } = false;

        /// <summary>
        /// 取得输出路径
        /// </summary>
        /// <param name="iOption">选项</param>
        /// <returns>输出路径</returns>
        protected string GetDataPath(SAssetOperateOptions iOption)
        {
            var dataDir = DataDir;
            if (string.IsNullOrEmpty(dataDir))
            {
                dataDir = EditorConst.WIN_FILE_DATA_DIR;
            }
            dataDir = $"{dataDir}/{GetType().Name}";

            if (SAssetOperateOptions.ImportJson == iOption ||
                SAssetOperateOptions.ExportJson == iOption ||
                SAssetOperateOptions.ForceClearJson == iOption)
            {
                return $"{dataDir}.json";
            }
            
            if (SAssetOperateOptions.ImportJsonAes == iOption ||
                SAssetOperateOptions.ExportJsonAes == iOption ||
                SAssetOperateOptions.ForceClearJsonAes == iOption)
            {
                return $"{dataDir}.aes";
            }
            
            if (SAssetOperateOptions.ImportJsonDes == iOption ||
                SAssetOperateOptions.ExportJsonDes == iOption ||
                SAssetOperateOptions.ForceClearJsonDes == iOption)
            {
                return $"{dataDir}.des";
            }

            if (SAssetOperateOptions.ImportTokenHs256 == iOption ||
                SAssetOperateOptions.ExportTokenHs256 == iOption ||
                SAssetOperateOptions.ForceClearTokenHs256 == iOption)
            {
                return $"{dataDir}_Hs256.token";
            }

            if (SAssetOperateOptions.ImportTokenHs384 == iOption ||
                SAssetOperateOptions.ExportTokenHs384 == iOption ||
                SAssetOperateOptions.ForceClearTokenHs384 == iOption)
            {
                return $"{dataDir}_Hs384.token";
            }

            if (SAssetOperateOptions.ImportTokenHs512 == iOption ||
                SAssetOperateOptions.ExportTokenHs512 == iOption ||
                SAssetOperateOptions.ForceClearTokenHs512 == iOption)
            {
                return $"{dataDir}_Hs512.token";
            }

            throw new UnknownWindowOperationException(this);
        }
        
#region Options

        /// <summary>
        /// 展开缩进
        /// </summary>
        public virtual bool Expandable => false;
        
        /// <summary>
        /// 可拖拽
        /// </summary>
        public virtual bool Draggable => false;

        /// <summary>
        /// 可排序
        /// </summary>
        public virtual bool Sortable => false;

        /// <summary>
        /// 可分页
        /// </summary>
        public virtual  bool Pageable => false;

        /// <summary>
        /// 可追加
        /// </summary>
        public virtual bool Addable => false;

        /// <summary>
        /// 可移除
        /// </summary>
        public virtual bool Removable => false;

        /// <summary>
        /// 可编辑
        /// </summary>
        public virtual bool Editable => false;

        /// <summary>
        /// 可检索
        /// </summary>
        public virtual bool Searchable => false;

        /// <summary>
        /// 可导入
        /// </summary>
        public virtual bool Importable => false;

        /// <summary>
        /// 可导出
        /// </summary>
        public virtual bool Exportable => false;

        /// <summary>
        /// 可清楚
        /// </summary>
        public virtual bool Clearable => false;
        
        /// <summary>
        /// 可帮助的
        /// <para>* 窗体右上角，工具栏处有帮助按钮</para>
        /// </summary>
        public virtual bool Helpful => false;

        /// <summary>
        /// 帮助文档Url
        /// </summary>
        protected virtual string HelpfulUrl => "https://docs.unity3d.com/Manual/index.html";

#endregion
        
        /// <summary>
        /// 窗口类不要写构造函数，初始化写在Awake里
        /// </summary>
        protected virtual void Awake()
        {
            // 初始化
            UtilsIo.Init();
        }

        protected void OnDestroy()
        {
            // 默认选项
            var defaultOptions = GetDefaultExportOption(Options);
            // 导出
            if (Exportable)
            {
                Export((int)defaultOptions);
            }
            
            // 窗体关闭回调
            OnWindowClosed();
        }

#region Init

        /// <summary>
        /// 初始化数据.
        /// </summary>
        protected virtual bool InitData()
        {
            // 导入数据
            var importOption = GetDefaultImportOption(Options);
            if (Importable && !Import((int)importOption))
            {
                this.Error("Init():Import Failed!(Options:{0})", importOption);
            }
            
            return true;
        }
        
        /// <summary>
        /// 选项按钮
        /// </summary>
        private static GUIContent _optionsIconBtn = null;

        /// <summary>
        /// 初始化Content
        /// </summary>
        protected virtual void InitGuiContents()
        {
            _optionsIconBtn = UtilsGUIEx.CreateGuiContentWithIcon(null, EditorConst.IconOptions);
        }

        /// <summary>
        /// 初始化Style
        /// </summary>
        protected virtual void InitGuiStyles() { }

        /// <summary>
        /// 初始化尺寸以及位置信息
        /// </summary>
        protected virtual void InitSizeRect() { }
        
        /// <summary>
        /// 初始化属性结构视图
        /// </summary>
        protected virtual void InitTreeView() {}
        
#endregion

#region CheckCode

        /// <summary>
        /// 校验码
        /// </summary>
        public virtual string CheckCode { get; } = null;

        /// <summary>
        /// 生成校验码
        /// </summary>
        /// <param name="iMode">校验模式(默认:Md5)</param>
        /// <returns>校验码</returns>
        protected abstract string GenCheckCode(CheckMode iMode = CheckMode.Md5);

#endregion

#region Events

        /// <summary>
        /// 选项菜单按钮点击事件
        /// </summary>
        /// <param name="iOptions">选项</param>
        protected abstract void OnOptionsMenuClicked(object iOptions);
        
        /// <summary>
        /// 窗体关闭回调
        /// </summary>
        protected virtual void OnWindowClosed() {}

#endregion

#region Options

        /// <summary>
        /// 窗体选项
        /// </summary>
        public int Options => (int)SAssetOperateOptions.WindowDefaultOptions;

        /// <summary>
        /// 窗体选项是否有效
        /// </summary>
        protected bool OptionsEnable => Options != (int)SAssetOperateOptions.None;

        /// <summary>
        /// 取得默认导入选项
        /// </summary>
        /// <param name="iOptions">选项</param>
        /// <returns>默认导入选项</returns>
        /// <exception cref="UnknownWindowOperationException"></exception>
        protected SAssetOperateOptions GetDefaultImportOption(int iOptions)
        {

            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportJson))
            {
                return SAssetOperateOptions.ImportJson;
            }
            
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportJsonAes))
            {
                return SAssetOperateOptions.ImportJsonAes;
            }
            
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportJsonDes))
            {
                return SAssetOperateOptions.ImportJsonDes;
            }
            
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportTokenHs256))
            {
                return SAssetOperateOptions.ImportTokenHs256;
            }
            
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportTokenHs384))
            {
                return SAssetOperateOptions.ImportTokenHs384;
            }
            
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportTokenHs512))
            {
                return SAssetOperateOptions.ImportTokenHs512;
            }
            
            throw new UnknownWindowOperationException(this);
        }

        /// <summary>
        /// 取得默认导出选项
        /// </summary>
        /// <param name="iOptions">选项</param>
        /// <returns>默认导出选项</returns>
        /// <exception cref="UnknownWindowOperationException"></exception>
        protected SAssetOperateOptions GetDefaultExportOption(int iOptions)
        {

            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportJson))
            {
                return SAssetOperateOptions.ExportJson;
            }
            
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportJsonAes))
            {
                return SAssetOperateOptions.ExportJsonAes;
            }
            
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportJsonDes))
            {
                return SAssetOperateOptions.ExportJsonDes;
            }
            
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportTokenHs256))
            {
                return SAssetOperateOptions.ExportTokenHs256;
            }
            
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportTokenHs384))
            {
                return SAssetOperateOptions.ExportTokenHs384;
            }
            
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportTokenHs512))
            {
                return SAssetOperateOptions.ExportTokenHs512;
            }
            
            throw new UnknownWindowOperationException(this);
        }
        
        /// <summary>
        /// 追加菜单Item
        /// </summary>
        /// <param name="iMenu">菜单</param>
        /// <param name="iMenuItemTxt">菜单选项文本</param>
        /// <param name="iOnOff">On/Off</param>
        /// <param name="iOnMenuItemClicked">菜单Item点击回调</param>
        /// <param name="iMenuItemOption">菜单选项</param>
        /// <param name="iAppendSeparator">是不是附加分割线</param>
        private void AddMenuItem(GenericMenu iMenu, string iMenuItemTxt, bool iOnOff, 
            GenericMenu.MenuFunction2 iOnMenuItemClicked, SAssetOperateOptions iMenuItemOption, 
            bool iAppendSeparator = false)
        {
            iMenu.AddItem(new GUIContent(iMenuItemTxt), iOnOff, iOnMenuItemClicked, iMenuItemOption);
            if (iAppendSeparator)
            {
                iMenu.AddSeparator("");
            }
        }

        /// <summary>
        /// 创建选项下拉菜单
        /// </summary>
        /// <param name="iOnOptionsMenuClicked">选项菜单点击事件</param>
        /// <returns>菜单</returns>
        private GenericMenu CreateOptionsMenu(GenericMenu.MenuFunction2 iOnOptionsMenuClicked)
        {
            var menu = new GenericMenu();

            // 导入
            // 导入 - Json/不加密
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ImportJson))
            {
                AddMenuItem(menu, "导入/Json/不加密", false, iOnOptionsMenuClicked, SAssetOperateOptions.ImportJson, true);
            }
            // 导入 - Json/Aes
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ImportJsonAes))
            {
                AddMenuItem(menu, "导入/Json/Aes", false, iOnOptionsMenuClicked, SAssetOperateOptions.ImportJsonAes);
            }
            // 导入 - Json/Des
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ImportJsonDes))
            {
                AddMenuItem(menu, "导入/Json/Des", false, iOnOptionsMenuClicked, SAssetOperateOptions.ImportJsonDes);
            }
            
            // 导入 - Token/Hs256
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ImportTokenHs256))
            {
                AddMenuItem(menu, "导入/Token/Hs256", false, iOnOptionsMenuClicked, SAssetOperateOptions.ImportTokenHs256);
            }
            // 导入 - Token/Hs384
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ImportTokenHs384))
            {
                AddMenuItem(menu, "导入/Token/Hs384", false, iOnOptionsMenuClicked, SAssetOperateOptions.ImportTokenHs384);
            }
            // 导入 - Token/Hs512
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ImportTokenHs512))
            {
                AddMenuItem(menu, "导入/Token/Hs512", false, iOnOptionsMenuClicked, SAssetOperateOptions.ImportTokenHs512);
            }
            
            // 导入 - Binary/不加密
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ImportBinary))
            {
                AddMenuItem(menu, "导入/Binary/不加密", false, iOnOptionsMenuClicked, SAssetOperateOptions.ImportBinary);
            }
            // 导入 - Binary/Aes
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ImportBinaryAes))
            {
                AddMenuItem(menu, "导入/Binary/Aes", false, iOnOptionsMenuClicked, SAssetOperateOptions.ImportBinaryAes);
            }
            // 导入 - Binary/Aes
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ImportBinaryDes))
            {
                AddMenuItem(menu, "导入/Binary/Des", false, iOnOptionsMenuClicked, SAssetOperateOptions.ImportBinaryDes);
            }
            
            // 导出
            // 导出 - Json/All
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ExportAll))
            {
                AddMenuItem(menu, "导出/All", false, iOnOptionsMenuClicked, SAssetOperateOptions.ExportAll, true);
                menu.AddSeparator("导出/");
            }
            
            // 导出 - Json/All
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ExportJsonAll))
            {
                AddMenuItem(menu, "导出/Json/All", false, iOnOptionsMenuClicked, SAssetOperateOptions.ExportJsonAll);
                menu.AddSeparator("导出/Json/");
            }
            // 导出 - Json/不加密
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ExportJson))
            {
                AddMenuItem(menu, "导出/Json/不加密", false, iOnOptionsMenuClicked, SAssetOperateOptions.ExportJson);
            }
            // 导出 - Binary/Aes
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ExportJsonAes))
            {
                AddMenuItem(menu, "导出/Json/Aes", false, iOnOptionsMenuClicked, SAssetOperateOptions.ExportJsonAes);
            }
            // 导出 - Binary/Des
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ExportJsonDes))
            {
                AddMenuItem(menu, "导出/Json/Des", false, iOnOptionsMenuClicked, SAssetOperateOptions.ExportJsonDes);
            }
            
            // 导出 - Token/All
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ExportTokenAll))
            {
                AddMenuItem(menu, "导出/Token/All", false, iOnOptionsMenuClicked, SAssetOperateOptions.ExportTokenAll);
                menu.AddSeparator("导出/Token/");
            }
            // 导出 - Token/Hs256
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ExportTokenHs256))
            {
                AddMenuItem(menu, "导出/Token/Hs256", false, iOnOptionsMenuClicked, SAssetOperateOptions.ExportTokenHs256);
            }
            // 导出 - Token/Hs384
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ExportTokenHs384))
            {
                AddMenuItem(menu, "导出/Token/Hs384", false, iOnOptionsMenuClicked, SAssetOperateOptions.ExportTokenHs384);
            }
            // 导出 - Token/Hs512
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ExportTokenHs512))
            {
                AddMenuItem(menu, "导出/Token/Hs512", false, iOnOptionsMenuClicked, SAssetOperateOptions.ExportTokenHs512);
            }
            
            // 导出 - Binary/All
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ExportBinaryAll))
            {
                AddMenuItem(menu, "导出/Binary/All", false, iOnOptionsMenuClicked, SAssetOperateOptions.ExportBinaryAll);
                menu.AddSeparator("导出/Binary/");
            }
            // 导出 - Binary/不加密
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ExportBinary))
            {
                AddMenuItem(menu, "导出/Binary/不加密", false, iOnOptionsMenuClicked, SAssetOperateOptions.ExportBinary);
            }
            // 导出 - Binary/Aes
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ExportBinaryAes))
            {
                AddMenuItem(menu, "导出/Binary/Aes", false, iOnOptionsMenuClicked, SAssetOperateOptions.ExportBinaryAes);
            }
            // 导出 - Binary/Des
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ExportBinaryDes))
            {
                AddMenuItem(menu, "导出/Binary/Des", false, iOnOptionsMenuClicked, SAssetOperateOptions.ExportBinaryDes);
            }
            
            // 强制清空
            // 强制清空 - All
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ForceClearAll))
            {
                AddMenuItem(menu, "强制清空/All", false, iOnOptionsMenuClicked, SAssetOperateOptions.ForceClearAll);
                menu.AddSeparator("强制清空/");
            }
            
            // 强制清空 - Json/All
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ForceClearJsonAll))
            {
                AddMenuItem(menu, "强制清空/Json/All", false, iOnOptionsMenuClicked, SAssetOperateOptions.ForceClearJsonAll);
                menu.AddSeparator("强制清空/Json/");
            }
            // 强制清空 - Json/不加密
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ForceClearJson))
            {
                AddMenuItem(menu, "强制清空/Json/不加密", false, iOnOptionsMenuClicked, SAssetOperateOptions.ForceClearJson);
            }
            // 强制清空 - Json/Aes
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ForceClearJsonAes))
            {
                AddMenuItem(menu, "强制清空/Json/Aes", false, iOnOptionsMenuClicked, SAssetOperateOptions.ForceClearJsonAes);
            }
            // 强制清空 - Json/Des
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ForceClearJsonDes))
            {
                AddMenuItem(menu, "强制清空/Json/Des", false, iOnOptionsMenuClicked, SAssetOperateOptions.ForceClearJsonDes);
            }
            
            // 强制清空 - Token/All
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ForceClearTokenAll))
            {
                AddMenuItem(menu, "强制清空/Token/All", false, iOnOptionsMenuClicked, SAssetOperateOptions.ForceClearTokenAll);
                menu.AddSeparator("强制清空/Token/");
            }
            // 强制清空 - Token/Hs256
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ForceClearTokenHs256))
            {
                AddMenuItem(menu, "强制清空/Token/Hs256", false, iOnOptionsMenuClicked, SAssetOperateOptions.ForceClearTokenHs256);
            }
            // 强制清空 - Token/Hs384
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ForceClearTokenHs384))
            {
                AddMenuItem(menu, "强制清空/Token/Hs384", false, iOnOptionsMenuClicked, SAssetOperateOptions.ForceClearTokenHs384);
            }
            // 强制清空 - Token/Hs512
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ForceClearTokenHs512))
            {
                AddMenuItem(menu, "强制清空/Token/Hs512", false, iOnOptionsMenuClicked, SAssetOperateOptions.ForceClearTokenHs512);
            }
            
            // 强制清空 - Binary/All
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ForceClearBinaryAll))
            {
                AddMenuItem(menu, "强制清空/Binary/All", false, iOnOptionsMenuClicked, SAssetOperateOptions.ForceClearBinaryAll);
                menu.AddSeparator("强制清空/Binary/");
            }
            // 强制清空 - Binary/不加密
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ForceClearBinary))
            {
                AddMenuItem(menu, "强制清空/Binary/不加密", false, iOnOptionsMenuClicked, SAssetOperateOptions.ForceClearBinary);
            }
            // 强制清空 - Binary/Aes
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ForceClearBinaryAes))
            {
                AddMenuItem(menu, "强制清空/Binary/Aes", false, iOnOptionsMenuClicked, SAssetOperateOptions.ForceClearBinaryAes);
            }
            // 强制清空 - Binary/Des
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ForceClearBinaryDes))
            {
                AddMenuItem(menu, "强制清空/Binary/Des", false, iOnOptionsMenuClicked, SAssetOperateOptions.ForceClearBinaryDes);
            }
            
            // 清空
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.Clear))
            {
                AddMenuItem(menu, "清空", false, iOnOptionsMenuClicked, SAssetOperateOptions.Clear);
            }
            
            // 帮助文档
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.Helpful))
            {
                AddMenuItem(menu, "帮助", false, iOnOptionsMenuClicked, SAssetOperateOptions.Helpful);
            }
            
            return menu;
        }

#endregion
        
#region Position&Size

        /// <summary>
        /// 余白 - 横向
        /// </summary>
        protected static readonly float HorizontalSpacing = EditorConst.HorizontalSpacing;

        /// <summary>
        /// 宽度 - Toggle
        /// </summary>
        protected static readonly float ToggleWidth = EditorConst.ToggleWidth;    

        /// <summary>
        /// 宽度 - 按钮 - 较短
        /// </summary>
        protected static readonly float BtnWidthShort = EditorConst.BtnWidthShort;

        /// <summary>
        /// 按钮 - 仅是Icon的按钮
        /// </summary>
        protected static readonly float BtnWidthIconOnly = EditorConst.BtnWidthIconOnly;   

        /// <summary>
        /// 余白 : 纵向
        /// </summary>
        protected static readonly float VerticalSpacing = EditorConst.VerticalSpacing;        
        
        /// <summary>
        /// 高度 - 单行
        /// </summary>
        protected static readonly float  SingleLineHeight = EditorConst.DefaultLineHeight;
                
        /// <summary>
        /// 头部高度
        /// </summary>
        protected static readonly float  HeaderHeight = SingleLineHeight + VerticalSpacing;
        
        /// <summary>
        /// 高度 - 状态Bar
        /// </summary>
        protected static readonly float StatusBarHeight = EditorConst.DefaultLineHeight;

        /// <summary>
        /// 窗体显示区域
        /// </summary>
        public Rect DisplayRect => position;

        /// <summary>
        /// 位置
        /// </summary>
        public Vector2 Pos => position.position;

        /// <summary>
        /// 窗体宽度
        /// </summary>
        public float Width => position.width;
        
        /// <summary>
        /// 窗体高度
        /// </summary>
        public float Height => position.height;

        /// <summary>
        /// Body区域
        /// </summary>
        protected Rect BodyRect => new Rect(
            HorizontalSpacing, VerticalSpacing,
            Width - HorizontalSpacing * 2, Height - VerticalSpacing * 2 - StatusBarHeight); 

#endregion

#region Window

        /// <summary>
        /// 打开
        /// </summary>
        public virtual void OpenWindow()
        {
            Show();
            Repaint();
        }

        /// <summary>
        /// 关闭
        /// </summary>
        public virtual void CloseWindow()
        {
            // 默认选项
            var defaultOptions = GetDefaultExportOption(Options);
            // 导出
            if (Exportable)
            {
                Export((int)defaultOptions);
            }
            
            // 窗体关闭回调
            OnWindowClosed();
            
            Close();
        }

#endregion
        
#region Drag
        
        protected virtual int DragAndDropHash => $"{GetType().Name}DragAndDrop".GetHashCode();
                
        /// <summary>
        /// 拖拽Control Id
        /// </summary>
        public int DragDropControlID { get; protected set; } = -1;
        
        /// <summary>
        /// 挂接拖拽
        /// </summary>
        /// <param name="iRect">区域</param>
        /// <param name="iEvent">Event</param>
        /// <param name="iOnDragAnDropped">拖拽回调</param>
        protected void HandleDragAndDrop(Rect iRect, Event iEvent, AssetsDragAndDropDown iOnDragAnDropped) 
        {

            switch (iEvent.GetTypeForControl(DragDropControlID)) 
            {
                // 拖拽更新
                case EventType.DragUpdated:
                // 执行拖拽
                case EventType.DragPerform:
					
                    if (GUI.enabled && iRect.Contains(iEvent.mousePosition)) 
                    {
                        var acceptDrag = false;
                        // 拖动文件或者文件夹
                        var paths = DragAndDrop.paths;
                        if (null != paths && 0 < paths.Length)
                        {
                            DragAndDrop.visualMode = DragAndDropVisualMode.Generic;
                            acceptDrag = true;

                            iOnDragAnDropped.Invoke(paths);
                        }
                        
                        if (acceptDrag) 
                        {
                            GUI.changed = true;
                            DragAndDrop.AcceptDrag();
                        }
                    }
                    break;

                case EventType.DragExited:
					
                    if (GUI.enabled) 
                    {
                        HandleUtility.Repaint();
                    }

                    break;
            }
        }
        
        /// <summary>
        /// 挂接拖拽
        /// </summary>
        /// <param name="iRect">区域</param>
        /// <param name="iEvent">Event</param>
        /// <param name="iOnDragAnDropped">拖拽回调</param>
        protected void HandleDragAndDrop<TObj>(Rect iRect, Event iEvent, ObjectsDragAndDropDown<TObj> iOnDragAnDropped) 
            where TObj : UnityEngine.Object
        {

            switch (iEvent.GetTypeForControl(DragDropControlID)) 
            {
                // 拖拽更新
                case EventType.DragUpdated:
                // 执行拖拽
                case EventType.DragPerform:
					
                    if (GUI.enabled && iRect.Contains(iEvent.mousePosition)) 
                    {
                        var acceptDrag = false;
                        // 拖拽对象引用列表
                        var objectReferences = DragAndDrop.objectReferences;
                        foreach (var referenceObj in objectReferences)
                        {
                            var targetObj = referenceObj as TObj;
                            
                            if (default(TObj) != targetObj) 
                            {
                                DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
                                if (iEvent.type == EventType.DragPerform) 
                                {
                                    iOnDragAnDropped.Invoke(targetObj);
                                    if (!acceptDrag)
                                    {
                                        acceptDrag = true;
                                    }
                                    DragAndDrop.activeControlID = 0;
                                }
                                else 
                                {
                                    DragAndDrop.activeControlID = DragDropControlID;
                                }
                            }
                        }
                        if (acceptDrag) 
                        {
                            GUI.changed = true;
                            DragAndDrop.AcceptDrag();
                        }
                    }
                    break;

                case EventType.DragExited:
					
                    if (GUI.enabled) 
                    {
                        HandleUtility.Repaint();
                    }

                    break;
            }
        }

#endregion

#region Action

        /// <summary>
        /// 导入
        /// </summary>
        /// <returns>true:成功; false:失败;</returns>
        public bool Import()
        {
            // 默认选项
            var defaultOptions = GetDefaultExportOption(Options);
            
            // 导入
            return Import((int)defaultOptions);
        }

        /// <summary>
        /// 导入
        /// </summary>
        /// <param name="iOptions">导入选项(Json-不加密)</param>
        /// <returns>true:成功; false:失败;</returns>
        public abstract bool Import(int iOptions);

        /// <summary>
        /// 导出
        /// </summary>
        public void Export()
        {
            if(!Exportable) return;
            // 默认选项
            var defaultOptions = GetDefaultExportOption(Options);
            Export((int)defaultOptions);
        }

        /// <summary>
        /// 导出
        /// </summary>
        /// <param name="iOptions">导入选项(Json-不加密)</param>
        /// <returns>导出文件地址</returns>
        public abstract void Export(int iOptions);

        /// <summary>
        /// 清空
        /// </summary>
        /// <param name="iOptions">清空选项</param>
        public abstract void Clear(int iOptions = (int)SAssetOperateOptions.Clear);

        /// <summary>
        /// 刷新
        /// </summary>
        public virtual void Refresh() {}

        /// <summary>
        /// Apply
        /// </summary>
        public virtual void Apply() {}

#endregion
        
#region Draw
        
        protected virtual void OnGUI()
        {
            if (!Initialized)
            {
                // 初始化Style
                InitGuiStyles();

                // 初始化Content
                InitGuiContents();
                
                // 初始化尺寸以及位置信息
                InitSizeRect();
                
                // 初始化属性结构视图
                InitTreeView();
                Initialized = true;
            }

            var curEvent = Event.current;
            
            // 绘制Body
            var bodyRect = DrawWinBody(BodyRect, curEvent);

            var statusBarRect = BodyRect;
            statusBarRect.yMin = BodyRect.yMax;
            statusBarRect.height = StatusBarHeight;
            statusBarRect = DrawStatusBar(statusBarRect, curEvent);

            // 刷新列表
            if (NeedRefresh)
            {
                Refresh();
                NeedRefresh = false;
            }
        }
        
        /// <summary>
        /// 绘制工具栏按钮
        /// </summary>
        /// <param name="iPosition">位置</param>
        protected virtual void ShowButton(Rect iPosition)
        {
            if(!Importable && !Exportable && !Clearable) return;
            
            var curEvent = Event.current;
            var optionsBtnRect = iPosition;
            optionsBtnRect.xMin -= 1;
            optionsBtnRect.xMax += 1;
            optionsBtnRect.yMin -= 1;
            optionsBtnRect.yMax += 1;
            var rect = optionsBtnRect;
            optionsBtnRect = UtilsGUIEx.DrawButton(optionsBtnRect, curEvent, _optionsIconBtn,
                () =>
                {
                    var menu = CreateOptionsMenu(OnOptionsMenuClicked);
                    menu.DropDown(rect);
                    //Application.OpenURL(HelpfulUrl);
                }, Color.clear, GuiExHelper.PreButton);
        }
        
        /// <summary>
        /// 绘制窗体Body
        /// </summary>
        /// <param name="iRect">制矩形范围</param>
        /// <param name="iEvent">Event</param>
        /// <returns>制矩形范围</returns>
        protected abstract Rect DrawWinBody(Rect iRect, Event iEvent);

        /// <summary>
        /// 绘制状态Bar
        /// </summary>
        /// <param name="iRect">制矩形范围</param>
        /// <param name="iEvent">Event</param>
        /// <returns>制矩形范围</returns>
        protected virtual Rect DrawStatusBar(Rect iRect, Event iEvent)
        {
            var displayRect = iRect;

            var bgRect = UtilsGUIEx.DrawGenericBg(displayRect, iEvent);
            

            return displayRect;
        }

#endregion

    }

    /// <summary>
    /// 窗口基类
    /// </summary>
    /// <typeparam name="TConf">窗体配置类型</typeparam>
    public abstract class WindowBase<TConf> : WindowBase, IWindow<TConf>
        where TConf : JsonData, IWindowConf
    {
        
#region Conf

        /// <summary>
        /// 配置信息
        /// </summary>
        public TConf Conf { get; protected set; } = null;

        /// <summary>
        /// 重置配置信息
        /// </summary>
        /// <param name="iConf">配置信息</param>
        public void ResetConf(TConf iConf)
        {
            // 初始化
            UtilsIo.Init();
            
            if(null == iConf || !iConf.Valid) return;
            Conf = iConf;
            
            // 初始化
            if (!InitData())
            {
                this.Warning("ResetConf()::InitData Failed!");
                return;
            }
        }

#endregion

#region CheckCode

        private string _checkCode = null;

        /// <summary>
        /// 校验码
        /// </summary>
        public override string CheckCode
        {
            get
            {
                if (!string.IsNullOrEmpty(_checkCode)) return _checkCode;
                _checkCode = GenCheckCode();
                return _checkCode;
            }
        }

        /// <summary>
        /// 生成校验码
        /// </summary>
        /// <param name="iMode">校验模式(默认:Md5)</param>
        /// <returns>校验码</returns>
        protected override string GenCheckCode(CheckMode iMode = CheckMode.Md5) => UtilsCheckCode.Encode(Conf, iMode, false);

#endregion

    }

    /// <summary>
    /// 窗口基类
    /// </summary>
    /// <typeparam name="TWin">窗体类型</typeparam>
    /// <typeparam name="TConf">窗体配置类型</typeparam>
    /// <typeparam name="TData">窗体数据类型</typeparam>
    public abstract class WindowBase<TWin, TConf, TData> : WindowBase<TConf>, IWindow<TConf, TData>
        where TWin : WindowBase, IWindow<TConf, TData>
        where TConf : JsonData, IWindowConf
        where TData : JsonData, IWindowData, new()
    {

#region Create
        
        /// <summary>
        /// 显示窗体
        /// </summary>
        /// <param name="iConf">配置信息</param>
        /// <param name="iAttachable">窗体可挂接(可以挂接到别的窗体)</param>
        /// <param name="iReOpen">重新打开标志位</param>
        protected static TWin ShowWindow(TConf iConf, bool iAttachable = true, bool iReOpen = false)
        {
            //创建窗口	
            var window = UtilsWindow.CreateWindow<TWin, TConf>(iConf, iAttachable, iReOpen);	
            if (null == window) {
                HLogger.Error ("WindowBase::ShowWindow() -> Create Window Failed!!");
                return default(TWin);
            }
            window.ResetConf(iConf);
            window.OpenWindow();
            return window;
        }
        
#endregion

#region Paths
        
        /// <summary>
        /// 取得Json文件路径
        /// </summary>
        /// <param name="iOption">选项</param>
        /// <returns>Json文件路径</returns>
        private string GetJsonDataFilePath(SAssetOperateOptions iOption) => GetDataPath(iOption);

        /// <summary>
        /// 取得加密文件路径 - Aes
        /// </summary>
        /// <param name="iOption">选项</param>
        /// <returns>加密文件路径</returns>
        private string GetAesDataFilePath(SAssetOperateOptions iOption) => GetDataPath(iOption);

        /// <summary>
        /// 取得加密文件路径 - Des
        /// </summary>
        /// <param name="iOption">选项</param>
        /// <returns>加密文件路径</returns>
        private string GetDesDataFilePath(SAssetOperateOptions iOption) => GetDataPath(iOption);

        /// <summary>
        /// 取得Token文件路径
        /// </summary>
        /// <param name="iOption">选项</param>
        /// <returns>Token文件路径</returns>
        private string GetTokenDataFilePath(SAssetOperateOptions iOption) => GetDataPath(iOption);

#endregion

#region Events

        /// <summary>
        /// 选项菜单按钮点击事件
        /// </summary>
        /// <param name="iOptions">选项</param>
        protected override void OnOptionsMenuClicked(object iOptions)
        {
            var operateOptions = (int)iOptions;
            // 清空
            if(UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.Clear))
            {
                Data?.Clear();
                return;
            }
            
            // Json相关操作
            if (UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ImportJson) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ImportJsonAes) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ImportJsonDes) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ExportJson) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ExportJsonAes) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ExportJsonDes) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ForceClearJson) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ForceClearJsonAes) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ForceClearJsonDes))
            {
                DoJsonOperateOptions(operateOptions, CheckCode);
            }
            
            // Token相关操作
            if (UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ImportTokenHs256) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ImportTokenHs384) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ImportTokenHs512) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ExportTokenHs256) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ExportTokenHs384) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ExportTokenHs512) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ForceClearTokenHs256) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ForceClearTokenHs384) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ForceClearTokenHs512))
            {
                DoTokenOperateOptions(operateOptions, CheckCode);
            }
            
            // 清空
            if (UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ImportBinary) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ImportBinaryAes) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ImportBinaryDes) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ExportBinary) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ExportBinaryAes) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ExportBinaryDes) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ForceClearBinary) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ForceClearBinaryAes) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ForceClearBinaryDes))
            {
                //Self.Clear(operateOptions);
                //Dirty = true;
            }
            
            // 帮助
            if (UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.Helpful))
            {
                OnOptionHelpfulClicked();
            }
        }

        /// <summary>
        /// 选项菜单点击事件 - 帮助
        /// </summary>
        protected virtual void OnOptionHelpfulClicked()
        {
            if(string.IsNullOrEmpty(HelpfulUrl)) return;
            Application.OpenURL(HelpfulUrl);
        }

        /// <summary>
        /// Json相关的操作
        /// </summary>
        /// <param name="iOptions">操作选项</param>
        /// <param name="iSecretKey">密钥</param>
        protected virtual void DoJsonOperateOptions(int iOptions, string iSecretKey = null)
        {
            // 导入 - Json/不加密
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportJson))
            {
                var jsonPath = GetJsonDataFilePath(SAssetOperateOptions.ImportJson);
                var jsonFileIo = JsonFileIO<TData>.Create(Data, jsonPath);
                jsonFileIo?.Import((iSucceeded) =>
                {
                    if(!iSucceeded) return;

                    // 应用数据
                    var dirty = Data.ApplyData(jsonFileIo.Data);
                    if (dirty)
                    {
                        Refresh();
                    }
                });
                return;
            }
            
            // 导入 - Json/Aes
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportJsonAes))
            {
                var aesPath = GetAesDataFilePath(SAssetOperateOptions.ImportJsonAes);
                var aesFileIo = JsonAesFileIO<TData>.Create(Data, Encoding.UTF8, aesPath, iSecretKey);
                aesFileIo?.Import((iSucceeded) =>
                {
                    if(!iSucceeded) return;

                    // 应用数据
                    var dirty = Data.ApplyData(aesFileIo.Data);
                    if (dirty)
                    {
                        Refresh();
                    }
                });
                return;
            }
            
            // 导入 - Json/Des
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportJsonDes))
            {
                var aesPath = GetDesDataFilePath(SAssetOperateOptions.ImportJsonDes);
                var aesFileIo = JsonDesFileIO<TData>.Create(Data, Encoding.UTF8, aesPath, iSecretKey);
                aesFileIo?.Import((iSucceeded) =>
                {
                    if(!iSucceeded) return;

                    // 应用数据
                    var dirty = Data.ApplyData(aesFileIo.Data);
                    if (dirty)
                    {
                        Refresh();
                    }
                });
                return;
            }
            
            // 导出 - Json/不加密
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportJson))
            {
                var jsonPath = GetJsonDataFilePath(SAssetOperateOptions.ExportJson);
                var jsonFileIo = JsonFileIO<TData>.Create(Data, jsonPath);
                jsonFileIo?.Export((iSucceeded) =>
                {
                    if(!iSucceeded) return;
                    // Dirty = true;
                });
            }
            
            // 导出 - Json/Aes
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportJsonAes))
            {
                var aesPath = GetAesDataFilePath(SAssetOperateOptions.ExportJsonAes);
                var aesFileIo = JsonAesFileIO<TData>.Create(Data, Encoding.UTF8, aesPath, iSecretKey);
                aesFileIo?.Export((iSucceeded) =>
                {
                    if(!iSucceeded) return;
                    // Dirty = true;
                });
            }
            
            // 导出 - Json/Des
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportJsonDes))
            {
                var aesPath = GetDesDataFilePath(SAssetOperateOptions.ExportJsonDes);
                var aesFileIo = JsonDesFileIO<TData>.Create(Data, Encoding.UTF8, aesPath, iSecretKey);
                aesFileIo?.Export((iSucceeded) =>
                {
                    if(!iSucceeded) return;
                    // Dirty = true;
                });
            }
            
            // 强制清空 - Json/不加密
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearJson))
            {
                var jsonPath = GetJsonDataFilePath(SAssetOperateOptions.ForceClearJson);
                var jsonFileIo = JsonFileIO<TData>.Create(Data, jsonPath);
                var dirty = jsonFileIo?.Clear(true) ?? false;
                if (dirty)
                {
                    Refresh();
                }
            }
            
            // 强制清空 - Json/Aes
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearJsonAes))
            {
                var aesPath = GetAesDataFilePath(SAssetOperateOptions.ForceClearJsonAes);
                var aesFileIo = JsonAesFileIO<TData>.Create(Data, Encoding.UTF8, aesPath, iSecretKey);
                var dirty = aesFileIo?.Clear(true) ?? false;
                if (dirty)
                {
                    Refresh();
                }
            }
            
            // 强制清空 - Json/Des
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearJsonDes))
            {
                var aesPath = GetDesDataFilePath(SAssetOperateOptions.ForceClearJsonDes);
                var aesFileIo = JsonDesFileIO<TData>.Create(Data, Encoding.UTF8, aesPath, iSecretKey);
                var dirty = aesFileIo?.Clear(true) ?? false;
                if (dirty)
                {
                    Refresh();
                }
            }
        }
        
        /// <summary>
        /// Token相关的操作
        /// </summary>
        /// <param name="iOptions">操作选项</param>
        /// <param name="iSecretKey">密钥</param>
        protected virtual void DoTokenOperateOptions(int iOptions, string iSecretKey = null)
        {
            // 导入 - Token - Hs256
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportTokenHs256))
            {
                var tokenPath = GetTokenDataFilePath(SAssetOperateOptions.ImportTokenHs256);
                var tokenFileIo = TokenFileIO<TData>.Create(Data, Encoding.UTF8, tokenPath, iSecretKey, TokenAlgorithms.Hs256);
                tokenFileIo?.Import((iSucceeded) =>
                {
                    if(!iSucceeded) return;

                    // 应用数据
                    var dirty = Data.ApplyData(tokenFileIo.Data);
                    if (dirty)
                    {
                        Refresh();
                    }
                });
                return;
            }
            
            // 导入 - Token - Hs384
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportTokenHs384))
            {
                var tokenPath = GetTokenDataFilePath(SAssetOperateOptions.ImportTokenHs384);
                var tokenFileIo = TokenFileIO<TData>.Create(Data, Encoding.UTF8, tokenPath, iSecretKey, TokenAlgorithms.Hs384);
                tokenFileIo?.Import((iSucceeded) =>
                {
                    if(!iSucceeded) return;

                    // 应用数据
                    var dirty = Data.ApplyData(tokenFileIo.Data);
                    if (dirty)
                    {
                        Refresh();
                    }
                });
                return;
            }
            
            // 导入 - Token - Hs512
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportTokenHs512))
            {
                var tokenPath = GetTokenDataFilePath(SAssetOperateOptions.ImportTokenHs512);
                var tokenFileIo = TokenFileIO<TData>.Create(Data, Encoding.UTF8, tokenPath, iSecretKey, TokenAlgorithms.Hs512);
                tokenFileIo?.Import((iSucceeded) =>
                {
                    if(!iSucceeded) return;

                    // 应用数据
                    var dirty = Data.ApplyData(tokenFileIo.Data);
                    if (dirty)
                    {
                        Refresh();
                    }
                });
                return;
            }
            
            // 导出 - Token - Hs256
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportTokenHs256))
            {
                var tokenPath = GetTokenDataFilePath(SAssetOperateOptions.ExportTokenHs256);
                var tokenFileIo = TokenFileIO<TData>.Create(Data, Encoding.UTF8, tokenPath, iSecretKey, TokenAlgorithms.Hs256);
                tokenFileIo?.Export((iSucceeded) =>
                {
                    if(!iSucceeded) return;
                    // Dirty = true;
                });
            }
            
            // 导出 - Token - Hs384
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportTokenHs384))
            {
                var tokenPath = GetTokenDataFilePath(SAssetOperateOptions.ExportTokenHs384);
                var tokenFileIo = TokenFileIO<TData>.Create(Data, Encoding.UTF8, tokenPath, iSecretKey, TokenAlgorithms.Hs384);
                tokenFileIo?.Export((iSucceeded) =>
                {
                    if(!iSucceeded) return;
                    // Dirty = true;
                });
            }
            
            // 导出 - Token - Hs512
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportTokenHs512))
            {
                var tokenPath = GetTokenDataFilePath(SAssetOperateOptions.ExportTokenHs512);
                var tokenFileIo = TokenFileIO<TData>.Create(Data, Encoding.UTF8, tokenPath, iSecretKey, TokenAlgorithms.Hs512);
                tokenFileIo?.Export((iSucceeded) =>
                {
                    if(!iSucceeded) return;
                    // Dirty = true;
                });
            }
            
            // 强制清空 - Token - Hs256
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearTokenHs256))
            {
                var tokenPath = GetTokenDataFilePath(SAssetOperateOptions.ForceClearTokenHs256);
                var tokenFileIo = TokenFileIO<TData>.Create(Data, Encoding.UTF8, tokenPath, iSecretKey, TokenAlgorithms.Hs256);
                var dirty = tokenFileIo?.Clear(true) ?? false;
                if (dirty)
                {
                    Refresh();
                }
            }
            
            // 强制清空 - Token - Hs384
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearTokenHs384))
            {
                var tokenPath = GetTokenDataFilePath(SAssetOperateOptions.ForceClearTokenHs384);
                var tokenFileIo = TokenFileIO<TData>.Create(Data, Encoding.UTF8, tokenPath, iSecretKey, TokenAlgorithms.Hs384);
                var dirty = tokenFileIo?.Clear(true) ?? false;
                if (dirty)
                {
                    Refresh();
                }
            }
            
            // 强制清空 - Token - Hs512
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearTokenHs512))
            {
                var tokenPath = GetTokenDataFilePath(SAssetOperateOptions.ForceClearTokenHs512);
                var tokenFileIo = TokenFileIO<TData>.Create(Data, Encoding.UTF8, tokenPath, iSecretKey, TokenAlgorithms.Hs512);
                var dirty = tokenFileIo?.Clear(true) ?? false;
                if (dirty)
                {
                    Refresh();
                }
            }
        }
        
#endregion
        
#region Options

        /// <summary>
        /// 展开缩进
        /// </summary>
        public override bool Expandable => Conf?.Expandable ?? false;
        
        /// <summary>
        /// 可拖拽
        /// </summary>
        public override bool Draggable => Conf?.Draggable ?? false;

        /// <summary>
        /// 可排序
        /// </summary>
        public override bool Sortable => Conf?.Sortable ?? false;

        /// <summary>
        /// 可分页
        /// </summary>
        public override  bool Pageable => Conf?.Pageable ?? false;

        /// <summary>
        /// 可追加
        /// </summary>
        public override bool Addable => Conf?.Addable ?? false;

        /// <summary>
        /// 可移除
        /// </summary>
        public override bool Removable => Conf?.Removable ?? false;

        /// <summary>
        /// 可编辑
        /// </summary>
        public override bool Editable => Conf?.Editable ?? false;

        /// <summary>
        /// 可检索
        /// </summary>
        public override bool Searchable => Conf?.Searchable ?? false;

        /// <summary>
        /// 可导入
        /// </summary>
        public override bool Importable => Conf?.Importable ?? false;

        /// <summary>
        /// 可导出
        /// </summary>
        public override bool Exportable => Conf?.Exportable ?? false;

        /// <summary>
        /// 可清楚
        /// </summary>
        public override bool Clearable => Conf?.Clearable ?? false;
        
        /// <summary>
        /// 可帮助的
        /// <para>* 窗体右上角，工具栏处有帮助按钮</para>
        /// </summary>
        public override bool Helpful => Conf?.Helpful ?? false;

#endregion

#region CheckCode

        /// <summary>
        /// 生成校验码
        /// </summary>
        /// <param name="iMode">校验模式(默认:Md5)</param>
        /// <returns>校验码</returns>
        protected override string GenCheckCode(CheckMode iMode = CheckMode.Md5) => UtilsCheckCode.Encode(Data, iMode, false);

#endregion

#region Data
        
        /// <summary>
        /// 窗体数据
        /// </summary>
        public TData Data { get; private set; } = new TData();

#endregion

#region Actions
        
        /// <summary>
        /// 导入
        /// </summary>
        /// <param name="iOptions">导入选项</param>
        /// <returns>true:成功; false:失败;</returns>
        public override bool Import(int iOptions)
        {
            
            var flg = false;
            // Json相关的操作
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportJson) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportJsonAes) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportJsonDes))
            {
                DoJsonOperateOptions(iOptions, CheckCode);
                flg = true;
            }
            
            // Token相关操作
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportTokenHs256) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportTokenHs384) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportTokenHs512))
            {
                DoTokenOperateOptions(iOptions, CheckCode);
                flg = true;
            }
            
            // 二进制相关
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportBinary) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportBinaryAes) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportBinaryDes))
            {
                this.Warning("Import():尚未支持二进制导入, 敬请期待!(Options:{0})", iOptions);
                flg = true;
            }
            
            if(flg) return true;
            this.Error("Import():Unknown Operation Options:{0}", iOptions);
            return false;
        }

        /// <summary>
        /// 导出
        /// </summary>
        /// <param name="iOptions">导出选项</param>
        public override void Export(int iOptions)
        {
            // 若尚无校验码，则生成校验码
            var flg = false;
            // Json相关的操作
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportJson) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportJsonAes) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportJsonDes))
            {
                DoJsonOperateOptions(iOptions, CheckCode);
                flg = true;
            }
            
            // Token相关操作
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportTokenHs256) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportTokenHs384) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportTokenHs512))
            {
                DoTokenOperateOptions(iOptions, CheckCode);
                flg = true;
            }
            
            // 二进制相关
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportBinary) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportBinaryAes) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportBinaryDes))
            {
                this.Warning("Import():尚未支持二进制导出, 敬请期待!(Options:{0})", iOptions);
                flg = true;
            }

            if (flg)
            {
                UtilsSEAssets.AssetsRefresh();
                return;
            }
            this.Error("Export():Unknown Operation Options:{0}", iOptions);
        }

        /// <summary>
        /// 清空
        /// </summary>
        /// <param name="iOptions">清空选项</param>
        public override void Clear(int iOptions = (int)SAssetOperateOptions.Clear)
        {
            // 清空
            if(UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.Clear))
            {
                Data?.Clear();
            }
            
            var flg = false;
            // Json相关的操作
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearJson) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearJsonAes) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearJsonDes))
            {
                DoJsonOperateOptions(iOptions);
                flg = true;
            }
            
            // Token相关操作
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearTokenHs256) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearTokenHs384) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearTokenHs512))
            {
                DoTokenOperateOptions(iOptions);
                flg = true;
            }
            
            // 二进制相关
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearBinary) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearBinaryAes) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearBinaryDes))
            {
                this.Warning("Import():尚未支持二进制强制清空, 敬请期待!(Options:{0})", iOptions);
                flg = true;
            }
            
            if(flg) return;
            this.Error("Clear():Unknown Operation Options:{0}", iOptions);
        }

        
        
#endregion

    }
}
